﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;
using System.Text.RegularExpressions;

namespace NFinalCompiler.Sql
{
    public class SqlDocument
    {
        public Dictionary<string, string> varList = new Dictionary<string, string>();
        public bool generateAllTable = true;
        public string generateMode = "model";
        public string name = null;
        public string modelNameSpace = null;
        public string bllNameSpace = null;
        public string connectionString = null;
        public string providerName = null;
        public string keyAttribute = null;
        public string tableAttribute = null;
        public string columnAttribute = null;

        public Dictionary<string, string> sqlList = new Dictionary<string, string>();
        public List<ModelFileData> modelFileDataList = new List<ModelFileData>();
        public List<string> fileNameList = new List<string>();
        public static string nameSpace;
        public SqlDocument(string filePath, string nameSpace, string sqlContent)
        {
            SqlDocument.nameSpace = nameSpace;
            modelNameSpace = nameSpace;
            bllNameSpace = nameSpace;
            string fileDirectory = Path.GetDirectoryName(filePath);
            if (!Directory.Exists(fileDirectory))
            {
                Directory.CreateDirectory(fileDirectory);
            }
            string fileName;
            NFinal.IO.StringWriter sw = null;
            ModelFileData modelData;
            System.Data.Common.DbConnection con = null;
            #region 读取配置
            Regex commentRegex = new Regex(@"/\*(.*?)\*/", RegexOptions.Singleline);
            Match commentMatch = commentRegex.Match(sqlContent);
            if (commentMatch.Success && commentMatch.Groups[1].Success)
            {
                string commentContent = commentMatch.Groups[1].Value;
                Regex varRegex = new Regex(@"set\s+@([_a-zA-Z0-9]+)=('.*?'|.*)(\r|\n)*", RegexOptions.Singleline | RegexOptions.IgnoreCase);
                MatchCollection varMac = varRegex.Matches(commentContent);
                string key = null;
                string value = null;
                foreach (Match varMat in varMac)
                {
                    if (varMat.Success)
                    {
                        key = varMat.Groups[1].Value;
                        value = varMat.Groups[2].Value.Trim().Trim('\'');
                        if (!string.IsNullOrEmpty(key))
                        {
                            if (key == "generateAllTable")
                            {
                                if (value == "true" || value == "1")
                                {
                                    generateAllTable = true;
                                }
                                else
                                {
                                    generateAllTable = false;
                                }
                            }
                            else if (key == "name")
                            {
                                this.name = value;
                            }
                            else if (key == "modelNameSpace")
                            {
                                if (!string.IsNullOrEmpty(value))
                                {
                                    this.modelNameSpace = value.Trim('.');
                                }
                            }
                            else if (key == "bllNameSpace")
                            {
                                if (!string.IsNullOrEmpty(value))
                                {
                                    this.bllNameSpace = value.Trim('.');
                                }
                            }
                            else if (key == "generateMode")
                            {
                                if (!string.IsNullOrEmpty(value))
                                {
                                    generateMode = value;
                                }
                                else
                                {
                                    generateMode = "model";
                                }
                            }
                            else if (key == "connectionString")
                            {
                                this.connectionString = value;
                            }
                            else if (key == "providerName")
                            {
                                this.providerName = value;
                            }
                            else if (key == "tableAttribute")
                            {
                                this.tableAttribute = value;
                            }
                            else if (key == "columnAttribute")
                            {
                                this.columnAttribute = value;
                            }
                            else if (key == "keyAttribute")
                            {
                                this.keyAttribute = value;
                            }
                        }
                    }
                }
            }
            #endregion
            Data.DataUtility dataUtility = null;
            string id= AppDomain.CurrentDomain.BaseDirectory;
            string dataBaseType = "";
            if (!string.IsNullOrEmpty(this.name) && !string.IsNullOrEmpty(this.connectionString) && !string.IsNullOrEmpty(this.providerName))
            {
                if (this.providerName.ToLower().IndexOf("mysql") > -1)
                {
                    dataBaseType = "mysql";
                    con = new MySql.Data.MySqlClient.MySqlConnection(connectionString);
                    dataUtility = new Data.MySqlDataUtility(con);
                }
                else if (this.providerName.ToLower().IndexOf("sqlite") > -1)
                {
                    dataBaseType = "sqlite";
                    con = new System.Data.SQLite.SQLiteConnection(connectionString);
                    dataUtility = new Data.SQLiteDataUtility(con);
                }
                else if (this.providerName.ToLower().IndexOf("sqlclient") > -1)
                {
                    dataBaseType = "sqlserver";
                    con = new System.Data.SqlClient.SqlConnection(connectionString);
                    dataUtility = new Data.SqlServerDataUtility(con);
                }
                else if (this.providerName.ToLower().IndexOf("Oracle") > -1)
                {
                    dataBaseType = "oracle";
                    con = new Oracle.ManagedDataAccess.Client.OracleConnection(connectionString);
                    dataUtility = new Data.OracleDataUtility(con);
                }
                else if (this.providerName.ToLower().IndexOf("Npgsql") > -1)
                {
                    dataBaseType = "npgsql";
                    con = new Npgsql.NpgsqlConnection(connectionString);
                    dataUtility = new Data.PostgreSqlDataUtility(con);
                }
                dataUtility.Open();
                #region 老的生成
                if (false)
                {
                    var tableDataList = dataUtility.GetDefaultTableData();
                    if (dataUtility != null)
                    {
                        //dataUtility.SetTableColumnData(tableDataList);
                        foreach (var tableData in tableDataList)
                        {
                            fileName = Path.Combine(fileDirectory, tableData.Name + ".cs");
                            if (!File.Exists(fileName))
                            {
                                modelData = new ModelFileData();
                                modelData.tableAttribute = this.tableAttribute;
                                modelData.columnAttribute = this.columnAttribute;
                                modelData.keyAttribute = this.keyAttribute;
                                modelData.name = tableData.Name;
                                modelData.nameSpace = nameSpace;
                                modelData.isDefaultTable = true;
                                dataUtility.SetTableColumnData(tableData);
                                sw = new NFinal.IO.StringWriter();
                                ModelTemplateRazor template = new ModelTemplateRazor(sw, tableData);
                                template.Execute();
                                modelData.content = sw.ToString();
                                modelData.fileName = fileName;
                                modelFileDataList.Add(modelData);
                            }
                        }
                    }
                }
                #endregion
                #region 新的生成
                if (generateAllTable)
                {
                    var dbReader = new DatabaseSchemaReader.DatabaseReader(con);
                    //Then load the schema (this will take a little time on moderate to large database structures)
                    var schema = dbReader.ReadAll();
                    dbReader.ReadAll();
                    foreach (var table in schema.Tables)
                    {
                        SqlModel.ModelData modelDataSchema = new SqlModel.ModelData();
                        modelDataSchema.BLLNameSpace = bllNameSpace;
                        modelDataSchema.ModelNameSpace = modelNameSpace;
                        modelDataSchema.DataBaseName = con.Database;
                        modelDataSchema.DataBaseShortName = this.name;
                        modelDataSchema.DataBaseType = dataBaseType;
                        modelDataSchema.Table = table;
                        if (generateMode == "model")
                        {
                            fileName = Path.Combine(fileDirectory, SqlModel.ModelHelper.GetTableName(table) + "Info.cs");
                            if (!File.Exists(fileName))
                            {
                                sw = new NFinal.IO.StringWriter();
                                SqlModel.NetStandard.ModelRazor model_Cshtml = new SqlModel.NetStandard.ModelRazor(sw, modelDataSchema);
                                model_Cshtml.Execute();
                                modelData = new ModelFileData();
                                modelData.fileName = fileName;
                                modelData.content = sw.ToString();
                                modelFileDataList.Add(modelData);
                            }
                        }
                        if (generateMode == "bll")
                        {
                            fileName = Path.Combine(fileDirectory,SqlModel.ModelHelper.GetTableName(table)+"BLL.cs");
                            if (!File.Exists(fileName))
                            {
                                sw = new NFinal.IO.StringWriter();
                                SqlModel.NetStandard.Bll_CacheRepostoryRazor bll_CacheRepostory_Cshtml = 
                                    new SqlModel.NetStandard.Bll_CacheRepostoryRazor(sw,modelDataSchema);
                                bll_CacheRepostory_Cshtml.Execute();
                                modelData = new ModelFileData();
                                modelData.fileName = fileName;
                                modelData.content = sw.ToString();
                                modelFileDataList.Add(modelData);
                            }
                        }
                    }
                }
                #endregion
            }
            #region
            if (false)
            {
                sqlContent = sqlContent.Substring(commentMatch.Length);
                StringReader reader = new StringReader(sqlContent);
                bool isEnd = false;
                string line = null;
                string name = null;
                string sql = null;
                while (!isEnd)
                {
                    line = reader.ReadLine();
                    if (line == null)
                    {
                        if (!string.IsNullOrEmpty(name))
                        {
                            sqlList.Add(name, sql);
                        }
                        break;
                    }
                    if (line.StartsWith("--"))
                    {
                        if (!string.IsNullOrEmpty(name))
                        {
                            sqlList.Add(name, sql);
                        }
                        name = line.Substring(2).Trim();
                        sql = null;
                    }
                    else
                    {
                        sql += line;
                    }
                }

                foreach (var sqlData in sqlList)
                {
                    fileName = Path.Combine(fileDirectory, sqlData.Key + ".cs");
                    if (!File.Exists(fileName))
                    {
                        modelData = new ModelFileData();
                        modelData.fileName = fileName;
                        modelData.name = sqlData.Key;
                        modelData.sql = sqlData.Value;
                        modelData.nameSpace = nameSpace;
                        modelData.isDefaultTable = false;
                        Data.TableData tableData = new Data.TableData(modelData.name, modelData.sql);
                        dataUtility.SetTableColumnData(tableData);
                        sw = new NFinal.IO.StringWriter();
                        ModelTemplateRazor modelTemplate = new ModelTemplateRazor(sw, tableData);
                        modelTemplate.Execute();
                        modelData.content = sw.ToString();
                        modelFileDataList.Add(modelData);
                    }
                }
            }
            #endregion
            dataUtility.Close();
        }
    }
}
